package com.xh.bussiness.tiku.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.exam.bean.dto.ExerciseStudentQuestionDto;
import com.xh.bussiness.jingyou.service.IJYQuestionService;
import com.xh.bussiness.system.model.Dictionary;
import com.xh.bussiness.system.service.IDictionaryService;
import com.xh.bussiness.tiku.bean.dto.*;
import com.xh.bussiness.tiku.bean.request.*;
import com.xh.bussiness.tiku.constant.TikuEsContant;
import com.xh.bussiness.tiku.dao.*;
import com.xh.bussiness.tiku.model.*;
import com.xh.bussiness.tiku.service.*;
import com.xh.bussiness.tiku.util.QuestionUtils;
import com.xh.core.bean.XhPage;
import com.xh.core.exception.XhException;
import com.xh.core.service.IElasticSearchService;
import com.xh.core.service.impl.BaseServiceImpl;
import com.xh.core.util.*;

import com.xh.tools.question.constant.QuestionTypeEnum;
import com.xh.tools.question.data.dto.QuestionDTO;
import com.xh.tools.question.data.dto.QuestionOptionDTO;
import org.apache.commons.lang3.RandomUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.stream.Collectors;

/**
 * <p>
 * 试题表 服务实现类
 * </p>
 *
 * @author daiwei
 * @since 2019-01-14
 */
@Service
public class QuestionServiceImpl extends BaseServiceImpl<QuestionMapper, Question> implements IQuestionService {

    public static final Logger log = LoggerFactory.getLogger(QuestionServiceImpl.class);
    @Autowired
    private QuestionDetailMapper questionDetailMapper;
    @Autowired
    private QuestionVersionMapper questionVersionMapper;
    @Autowired
    private QuestionVersionDetailMapper questionVersionDetailMapper;
    @Autowired
    private QuestionUrlDownloadMapper questionUrlDownloadMapper;
    @Autowired
    private IElasticSearchService elasticSearchService;
    @Autowired
    private IQuestionKnowledgeService questionKnowledgeService;
    @Autowired
    private IQuestionChapterKnowledgeService questionChapterKnowledgeService;
    @Autowired
    private IKnowledgeService knowledgeService;
    @Autowired
    private IBookChapterService bookChapterService;
    @Autowired
    private IQuestionDetailService questionDetailService;
    @Autowired
    private IQuestionImportLogService questionImportLogService;
    @Autowired
    private IJYQuestionService jyquestionService;
    @Autowired
    private IQuestionTypeRelationService questionTypeRelationService;
    @Autowired
    private QuestionCopyMapper questionCopyMapper;
    @Autowired
    private IQuestionCollectService questionCollectService;
    @Autowired
    private IQuestionSourceService questionSourceService;
    @Autowired
    private IDictionaryService dictionaryService;
    @Autowired
    private ImportQuestionErrorLogService importQuestionErrorLogService;

    @Override
    public QuestionDto addQuestion(QuestionSaveRequest bean) {
        QuestionTypeRelation questionTypeRelation = questionTypeRelationService.queryByJyQuestionType(bean.getSubjectId(), bean.getType());
//        if (questionTypeRelation == null) {
//            throw new XhException("未识别此题型！");
//        }
        if (StringUtils.isEmpty(bean.getTitle())) {
            throw new XhException("题干不能为空！");
        }

        String answerStr = "";
        if (bean.getRightAnswer() != null) {
            JSONArray array = JSON.parseArray(bean.getRightAnswer().toJSONString());
            if( bean.getBasicQuestionType() == 7){
                JSONObject json = array.getJSONArray(0).getJSONObject(0);
                answerStr = json.getString("content");
            }else{
                JSONObject json = array.getJSONObject(0);
                answerStr = json.getString("content");
            }
        }

        String errMsg = "";
        //设置标签编辑
        QuestionDTO questionDTO = com.xh.tools.question.util.QuestionUtils.parse(questionTypeRelation.getToolQuestionType(), questionTypeRelation.getJyQuestionTypeName(), bean.getTitle(), answerStr, bean.getAnalysis());
        // 前台手动选了题型
        if (!CollectionUtils.isEmpty(questionDTO.getDataErrorMsg())) {
            errMsg = questionDTO.getDataErrorMsg().stream().collect(Collectors.joining(","));
        }

        QuestionDto questionDto = converQuestion(questionDTO);

        Question question = new Question();
        question.init();
        question.setTitle(questionDto.getTitle());

        question.setType(bean.getType());
        if (questionTypeRelation != null) {
            question.setBasicType(questionTypeRelation.getToolQuestionType());
            question.setBasicTypeName(questionTypeRelation.getToolQuestionTypeName());
        }
        question.setSubjectId(bean.getSubjectId());
        question.setDifficult(bean.getDifficult() == null ? null : bean.getDifficult());
        question.setGradeRangeId(bean.getGradeRangeId());
        question.setGradeId(bean.getGradeId());
        question.setYearId(bean.getYear());
        question.setCategory(bean.getCategory());
        question.setLabels(bean.getLabels());
        question.setSource(bean.getSource());
        question.setSourceFrom(1);
        question.setStatus(3);
        question.setFailReason(errMsg);

        question.setVideoPath(bean.getVideoPath());
        question.setSilentVideoPath(bean.getSilentVideoPath());
        question.setVoicePath(bean.getVoicePath());
//        question.setBasicType(questionTypeRelation.getToolQuestionType());

        if (bean.getOption() != null) {
            String option = bean.getOption().toJSONString();
//            option = option.replaceAll("<p","<span");
            question.setOptionContent(option);
        } else {
            question.setOptionContent(questionDto.getOption() == null ? "" : questionDto.getOption().toJSONString());
        }
        //阅读理解、完形填答案空借助工具类进行解析
        if (questionTypeRelation.getToolQuestionType().equals(QuestionTypeEnum.CLOZE.getValue()) || questionTypeRelation.getToolQuestionType().equals(QuestionTypeEnum.READING.getValue())) {
            question.setRightAnswer(questionDto.getRightAnswer() == null ? "" : questionDto.getRightAnswer().toJSONString());
        } else {
            question.setRightAnswer(bean.getRightAnswer() == null ? null : bean.getRightAnswer().toJSONString());
        }
        question.setQuestionMd5(question.genarateMd5());
        Question existsQues = queryByMd5AndSubject(question.getQuestionMd5(), question.getSubjectId());
        if (existsQues != null) {
            /*log.error(String.format("addQuestion has error：already exist by param(%s,%s)", question.getQuestionMd5(), question.getSubjectId()));
            throw new XhException("该试题已存在！");*/
            return getQuestion(existsQues.getId(), null, true, true, true, true, true);
        }

        // 计算选项的排列方式
        if( bean.getBasicQuestionType()==7){
            question.setOptionArrangements(2);
        }else{
            QuestionUtils.calculateOptionArrangements(question);
        }

        this.dao.insert(question);
        QuestionDetail questionDetail = new QuestionDetail();
        questionDetail.setId(question.getId());
        questionDetail.setAnalysis(bean.getAnalysis() == null ? "" : bean.getAnalysis());
        questionDetail.setExamPoint(bean.getExamPoint());
        questionDetail.setAnalysisPay(bean.getAnalysisPay());
        questionDetail.setAnalysisVideo(bean.getAnalysisVideo());
        questionDetailMapper.insert(questionDetail);

        //子试题
        if (!CollectionUtils.isEmpty(questionDto.getChilds())) {
            if (!CollectionUtils.isEmpty(questionDto.getChilds())) {
                //直接删除子试题
                QueryWrapper qw = new QueryWrapper();
                qw.eq("parent_id", question.getId());
                this.deleteByCondition(qw);
                //todo 添加子试题
                questionDto.setId(question.getId());
                saveChildrenQuestion(questionDto, questionDto.getChilds());
            }
        }
        if (!CollectionUtils.isEmpty(bean.getChilds())) {
            //直接删除子试题
            QueryWrapper qw = new QueryWrapper();
            qw.eq("parent_id", question.getId());
            this.deleteByCondition(qw);
            //todo 添加子试题
            questionDto.setId(question.getId());
            saveChildrenQuestion(questionDto, bean.getChilds());
        }


        //试题来源
        if (!CollectionUtils.isEmpty(bean.getQuestionSources())) {
            for (int i = 0; i < bean.getQuestionSources().size(); i++) {
                QuestionSource questionSource = bean.getQuestionSources().get(i);
                questionSource.setQuestionId(question.getId());
                questionSource.setOrderNo((i + 1));
                questionSourceService.insert(questionSource);
            }
        }
        //增加题目和章节关联
        addQuestionChapterKnowles(bean, question);
        // 增加题目和知识点关联
        addQuestionKnowledge(bean.getKnowledgePoints(), question);
        // 添加索引到es
        addQuestion2ES(question);

        QuestionDto result = getQuestion(question.getId(), null, true, true, true, true, true);
        return result;
    }

    public void saveChildrenQuestion(QuestionDto parent, List<QuestionDto> children) {
        if (CollectionUtils.isEmpty(children)) {
            return;
        }
        for (int i = 0; i < children.size(); i++) {
            QuestionDto child = children.get(i);
            Question question = new Question();
            question.init();
            question.setOrderNo((i + 1));
            question.setTitle(child.getTitle());
            question.setType(child.getType()==null?child.getBasicQuestionType() : child.getType());
            question.setBasicType(child.getBasicQuestionType());
            question.setSubjectId(child.getSubjectId());
            question.setDifficult(child.getDifficult());
            question.setGradeId(child.getGradeId());
            question.setParentId(parent.getId());
            question.setSourceFrom(1);
            if (child.getOption() != null) {
                question.setOptionContent(child.getOption().toJSONString());
            }
            if (child.getRightAnswer() != null) {
                question.setRightAnswer(child.getRightAnswer().toJSONString());
            }
            question.setQuestionMd5(question.genarateMd5());
            // 计算选项的排列方式
            QuestionUtils.calculateOptionArrangements(question);
            this.insert(question);

            QuestionDetail questionDetail = new QuestionDetail();
            questionDetail.setId(question.getId());
            questionDetail.setAnalysis(child.getAnalysis());
            questionDetail.setExamPoint(child.getExamPoint());
            questionDetail.setAnalysisPay(child.getAnalysisPay());
            questionDetail.setAnalysisVideo(child.getAnalysisVideo());
            questionDetailMapper.insert(questionDetail);

            if (!CollectionUtils.isEmpty(child.getChilds())) {
                //todo 添加子试题
                saveChildrenQuestion(child, child.getChilds());
            }
        }

    }

    @Override
    public QuestionDto editQuestion(QuestionSaveRequest bean) {

        QuestionTypeRelation questionTypeRelation = questionTypeRelationService.queryByJyQuestionType(bean.getSubjectId(), bean.getType());
        String errMsg = "";
        //题库编辑试题 不需要解析：前台题干选项答案分离
        QuestionDTO questionDTO = null;
        if (bean.getOperationType().equals(1)) {
            questionDTO = com.xh.tools.question.util.QuestionUtils.parse(bean.getBasicQuestionType(), questionTypeRelation.getJyQuestionTypeName(), bean.getTitle(), "", bean.getAnalysis());
            questionDTO.setDataErrorMsg(null);
        } else {
            //设置标签编辑
            questionDTO = com.xh.tools.question.util.QuestionUtils.parse(bean.getBasicQuestionType(), questionTypeRelation.getJyQuestionTypeName(), bean.getTitle(), bean.getAnswer() == null ? "" : bean.getAnswer(), bean.getAnalysis());
            if (bean.getAnswer() == null || bean.getAnswer() == "") {
                questionDTO.getDataErrorMsg().add("答案为空");
            }
        }
        // 前台手动选了题型
        if (!CollectionUtils.isEmpty(questionDTO.getDataErrorMsg())) {
            errMsg = String.join(",", questionDTO.getDataErrorMsg());
        }
        questionDTO.setSubjectId(bean.getSubjectId());
        QuestionDto dto = converQuestion(questionDTO);
        Question question = new Question();
        question.setId(bean.getId());
        question.setTitle(dto.getTitle());
        question.setType(bean.getType());
        if (questionTypeRelation != null) {
            question.setBasicType(questionTypeRelation.getToolQuestionType());
            question.setBasicTypeName(questionTypeRelation.getToolQuestionTypeName());
        }
        if (bean.getOperationType().equals(1) && bean.getRightAnswer() != null) {
            //题库编辑试题
            question.setRightAnswer(bean.getRightAnswer().toJSONString());
            //转换选项
            question.setOptionContent(bean.getOption() == null ? "" : bean.getOption().toJSONString());
        } else {
            //设置标签编辑
            question.setRightAnswer(dto.getRightAnswer() == null ? "" : dto.getRightAnswer().toJSONString());
            question.setOptionContent(dto.getOption() == null ? "" : dto.getOption().toJSONString());
        }
        question.setQuestionMd5(question.genarateMd5());
        question.setDifficult(bean.getDifficult());
        question.setSource(bean.getSource());
        question.setYearId(bean.getYear());
        question.setCategory(bean.getCategory());
        question.setGradeRangeId(bean.getGradeRangeId());
        question.setGradeId(bean.getGradeId());

        question.setVideoPath(bean.getVideoPath());
        question.setSilentVideoPath(bean.getSilentVideoPath());
        question.setVoicePath(bean.getVoicePath());

        if(bean.getBasicQuestionType()!=7){
            QuestionUtils.calculateOptionArrangements(question);
        }
        question.setFailReason(errMsg);
//        question.setOptionArrangements(bean.getOptionArrangements()!=null?bean.getOptionArrangements() : null);
//        if (StringUtils.isEmpty(errMsg)) {
        question.setStatus(3);
//        } else {
//            question.setStatus(-1);
//        }
        this.update(question);
        //增加题目和章节关联关系
        addQuestionChapterKnowles(bean, question);
        // 删除题目关联的额知识点
        questionKnowledgeService.deleteByQuestionId(question.getId());
        // 增加题目和知识点关联
        addQuestionKnowledge(bean.getKnowledgePoints(), question);
        // 题目详情
        QuestionDetail questionDetail = new QuestionDetail();
        questionDetail.setId(question.getId());
        questionDetail.setAnalysis(dto.getAnalysis() == null ? "" : dto.getAnalysis());
        questionDetail.setExamPoint(dto.getExamPoint());
        questionDetail.setAnalysisPay(dto.getAnalysisPay());
        questionDetail.setAnalysisVideo(dto.getAnalysisVideo());

        this.questionDetailMapper.updateById(questionDetail);

        if (!CollectionUtils.isEmpty(dto.getChilds())) {
            if (!CollectionUtils.isEmpty(dto.getChilds())) {
                //直接删除子试题
                QueryWrapper qw = new QueryWrapper();
                qw.eq("parent_id", question.getId());
                this.deleteByCondition(qw);
                //todo 添加子试题
                dto.setId(question.getId());
                saveChildrenQuestion(dto, dto.getChilds());
            }
        }

        if (!CollectionUtils.isEmpty(bean.getChilds())) {
            //直接删除子试题
            QueryWrapper qw = new QueryWrapper();
            qw.eq("parent_id", question.getId());
            this.deleteByCondition(qw);
            //todo 添加子试题
            dto.setId(question.getId());
            saveChildrenQuestion(dto, bean.getChilds());
        }
        //试题来源
        questionSourceService.deleteQuestionSourceByQuestionId(question.getId());
        if (!CollectionUtils.isEmpty(bean.getQuestionSources())) {
            for (int i = 0; i < bean.getQuestionSources().size(); i++) {
                QuestionSource questionSource = bean.getQuestionSources().get(i);
                questionSource.setQuestionId(question.getId());
                questionSource.setOrderNo((i + 1));
                questionSourceService.insert(questionSource);
            }
        }

        // 修改索引到es
        updateQuestion2ES(question);

        return getQuestion(bean.getId(), null, true, true, true, true, true);
    }

    @Override
    public Boolean editQuestionOptionArrangements(Question question) {
        return this.update(question);

    }

    @Override
    public String modifyQuestion(QuestionSaveRequest bean) {
        Question question = this.getById(bean.getId());
        if (question == null) {
            return "当前试题ID不存在";
        }
        QuestionDetail questionDetail = this.questionDetailMapper.selectById(question.getId());

        // 复制当前版本试题
        QuestionVersion questionVersion = new QuestionVersion();
        questionVersion.setQuestionId(question.getId());
        questionVersion.setVersion(question.getCurrentVersion());
        questionVersion.setTitle(question.getTitle());
        questionVersion.setType(question.getType());
        questionVersion.setSubjectId(question.getSubjectId());
        questionVersion.setDifficult(question.getDifficult());
        questionVersion.setOptionContent(question.getOptionContent());
        questionVersion.setRightAnswer(question.getRightAnswer());
        this.questionVersionMapper.insert(questionVersion);

        QuestionVersionDetail questionVersionDetail = new QuestionVersionDetail();
        questionVersionDetail.setId(questionVersion.getId());
        questionVersionDetail.setAnalysis(questionDetail.getAnalysis());
        questionVersionDetail.setExamPoint(questionDetail.getExamPoint());
        questionVersionDetail.setAnalysisPay(questionDetail.getAnalysisPay());
        questionVersionDetail.setAnalysisVideo(questionDetail.getAnalysisVideo());
        this.questionVersionDetailMapper.insert(questionVersionDetail);

        // 将变动内容保存至主表
        question.setTitle(bean.getTitle());
        question.setType(bean.getType());
        question.setSubjectId(bean.getSubjectId());
        question.setDifficult(bean.getDifficult());
        question.setGradeRangeId(bean.getGradeRangeId());
        question.setGradeId(bean.getGradeId());
        question.setYearId(bean.getYear());
        question.setCategory(bean.getCategory());
        question.setLabels(bean.getLabels());
        question.setSource(bean.getSource());
        if (bean.getOption() != null) {
            question.setOptionContent(bean.getOption().toJSONString());
        }
        if (bean.getRightAnswer() != null) {
            question.setRightAnswer(bean.getRightAnswer().toJSONString());
        }
        question.setQuestionMd5(question.genarateMd5());

        questionDetail.setAnalysis(bean.getAnalysis());
        questionDetail.setExamPoint(bean.getExamPoint());
        questionDetail.setAnalysisPay(bean.getAnalysisPay());

        // 试题版本号加一
        question.setCurrentVersion(question.getCurrentVersion() + 1);
        this.update(question);
        this.questionDetailMapper.updateById(questionDetail);
        //增加题目与章节关联
        addQuestionChapterKnowles(bean, question);
        // 删除题目关联的额知识点
        questionKnowledgeService.deleteByQuestionId(question.getId());
        // 增加题目和知识点关联
        addQuestionKnowledge(bean.getKnowledgePoints(), question);
        // 修改索引到es
        updateQuestion2ES(question);

        return null;
    }

    private void addQuestionKnowledge(List<String> knowledgePoints, Question question) {
        if (!CollectionUtils.isEmpty(knowledgePoints)) {
            knowledgePoints = knowledgePoints.stream().distinct().collect(Collectors.toList());
            List<QuestionKnowledge> list = new ArrayList<QuestionKnowledge>();
            for (String id : knowledgePoints) {
                QuestionKnowledge qk = new QuestionKnowledge();
                qk.setKnowledgeId(id);
                qk.setQuestionId(question.getId());
                list.add(qk);
            }
            questionKnowledgeService.batchInsert(list);
            // 知识点id集合
//			question.setKnowledgeIds(knowledgePoints);
        }
    }

    public void addQuestionChapterKnowles(QuestionSaveRequest bean, Question question) {
        //删除题目章节关联关系
        questionChapterKnowledgeService.deleteByQuestionId(question.getId());
        //将章节下的知识点保存到试题与知识点关系表中
        if (!CollectionUtils.isEmpty(bean.getChapterKnowles())) {
            List<String> knowledgeIds = bean.getChapterKnowles().stream().filter(item -> !StringUtils.isEmpty(item.getKnowledgeId())).map(QuestionChapterKnowledge::getKnowledgeId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(knowledgeIds)) {
                List<String> knowledgePoints = bean.getKnowledgePoints();
                if (!CollectionUtils.isEmpty(knowledgePoints)) {
                    knowledgePoints.addAll(knowledgeIds);
                    bean.setKnowledgePoints(knowledgePoints);
                } else {
                    bean.setKnowledgePoints(knowledgeIds);
                }
            }

            List<QuestionChapterKnowledge> list = new ArrayList<>();

            List<String> exists = new ArrayList<>();
            for (QuestionChapterKnowledge questionChapterKnowle : bean.getChapterKnowles()) {
                String knowledgeId = questionChapterKnowle.getKnowledgeId();
                //过滤重复数据
                String key = String.format("%s%s", questionChapterKnowle.getChapterId(), StringUtils.isEmpty(knowledgeId) ? "" : knowledgeId);
                if (!exists.contains(key)) {
                    questionChapterKnowle.setQuestionId(question.getId());
                    list.add(questionChapterKnowle);

                    exists.add(key);
                }
            }
            questionChapterKnowledgeService.batchInsert(list);
        }
    }

    @Override
    public String deleteQuestion(String id) {
        Question question = this.getById(id);
        if (question == null) {
            return "当前试题ID不存在";
        }
        question.deleteById(id);
        // 根据题目删除关联的知识点
        QueryWrapper<QuestionKnowledge> qw = new QueryWrapper<QuestionKnowledge>();
        qw.eq("question_id", id);
        questionKnowledgeService.deleteByCondition(qw);
        questionChapterKnowledgeService.deleteByQuestionId(id);
        //删除试题详情
        questionDetailService.deleteByQuestionId(id);
        // 删除试题来源
        questionSourceService.deleteQuestionSourceByQuestionId(id);
        // 删除es 中的索引
        elasticSearchService.deleteDocument(id, TikuEsContant.ES_INDEX_TIKU, TikuEsContant.TYPE.ES_INDEX_TYPE_QUESTION);
        return null;
    }

    @Override
    public QuestionDto getQuestion(String id, Integer version) {
        return getQuestion(id, version, true, true, true, false, true);
    }

    @Override
    public QuestionDto getQuestion(String id, Integer version, Boolean withRightAnswer, Boolean withKnowledge, Boolean withChapter, Boolean withChapterKnowledge, Boolean withQuestionSource) {
        Question question = this.getById(id);
        if (question == null) {
            log.error("当前试题id不存在：" + id);
            return null;
        }
        return getQuestion(question, version, withRightAnswer, withKnowledge, withChapter, withChapterKnowledge, withQuestionSource);
    }

    /**
     * 作业获取单题
     *
     * @param id
     * @param version
     * @param withRightAnswer
     * @param withKnowledge
     * @param withChapter
     * @param withChapterKnowledge
     * @param withQuestionSource
     * @return com.xh.bussiness.tiku.bean.dto.QuestionDto
     * @author 赵文博
     * @date 2021/5/8 14:35
     **/
    @Override
    public QuestionDto getPracticeQuestion(String id, Integer version, Boolean withRightAnswer, Boolean withKnowledge, Boolean withChapter, Boolean withChapterKnowledge, Boolean withQuestionSource) {
        Question question = this.dao.queryPracticeQuestion(id);
        if (question == null) {
            log.error("当前试题id不存在：" + id);
            return null;
        }
        return getQuestion(question, version, withRightAnswer, withKnowledge, withChapter, withChapterKnowledge, withQuestionSource);
    }

    @Override
    public QuestionDto getPracticeQuestion(String id, Integer version) {
        Question question = this.dao.queryPracticeQuestion(id);
        if (question == null) {
            log.error("当前试题id不存在：" + id);
            return null;
        }
        return getQuestion(question, version, true, true, true, false, true);
    }

    private void getQuestionKnowledge(QuestionDto bean, String questionId) {
        QuestionKnowledgeRequest questionKnowledgeRequest = new QuestionKnowledgeRequest();
        questionKnowledgeRequest.setQuestionId(questionId);

        List<QuestionKnowledge> questionKnowledges = questionKnowledgeService.queryQuestionKnowledge(questionKnowledgeRequest);
        if (!CollectionUtils.isEmpty(questionKnowledges)) {
            List<String> knowledgePoints = questionKnowledges.stream().map(item -> item.getKnowledgeId()).collect(Collectors.toList());
            bean.setKnowledgePoints(knowledgePoints);

            KnowledgeRequest knowledgeRequest = new KnowledgeRequest();
            knowledgeRequest.setIds(knowledgePoints.toArray(new String[knowledgePoints.size()]));
            List<Knowledge> knowledges = knowledgeService.queryKnowledge(knowledgeRequest);
            if (!CollectionUtils.isEmpty(knowledges)) {
                bean.setKnowledges(knowledges);
            }
        }
    }

    private void getQuestionChapter(QuestionDto bean, String questionId) {
        QuestionChapterRequest questionChapterRequest = new QuestionChapterRequest();
        questionChapterRequest.setQuestionId(questionId);
        List<QuestionChapterKnowledge> questionChapterKnowledges = questionChapterKnowledgeService.queryQuestionChapter(questionChapterRequest);

        if (!CollectionUtils.isEmpty(questionChapterKnowledges)) {
            List<String> chaptersIds = questionChapterKnowledges.stream().map(item -> item.getChapterId()).collect(Collectors.toList());
            bean.setChaptersIds(chaptersIds);

            BookChapterRequest bookChapterRequest = new BookChapterRequest();
            bookChapterRequest.setIds(chaptersIds.toArray(new String[chaptersIds.size()]));
            List<BookChapter> chapters = bookChapterService.queryBookChapter(bookChapterRequest);
            if (!CollectionUtils.isEmpty(chapters)) {
                bean.setBookChapters(chapters);
            }
        }
    }


    /**
     * 查询试题,默认查询没被删除的视图,因为作业里可能存在被删除的试题,特意把试题的查询分离出来
     *
     * @param question             试题
     * @param version              版本
     * @param withRightAnswer      是否格式化正确答案
     * @param withKnowledge        是否获取试题知识点
     * @param withChapter          是否获取试题章节
     * @param withChapterKnowledge 是否获取试题章节知识点关系
     * @param withQuestionSource   是否获取试题来源
     * @return com.xh.bussiness.tiku.bean.dto.QuestionDto
     * @author 赵文博
     * @date 2021/5/8 14:25
     **/
    private QuestionDto getQuestion(Question question, Integer version, Boolean withRightAnswer, Boolean withKnowledge, Boolean withChapter, Boolean withChapterKnowledge, Boolean withQuestionSource) {
        if (question.getType() == null) {
            question.setType(888);
        }
        withRightAnswer = withRightAnswer == null ? false : withRightAnswer;
        QuestionDetail questionDetail = questionDetailMapper.selectById(question.getId());
        QuestionDto bean = new QuestionDto();

        //获取试题知识点
        if (withKnowledge) {
            getQuestionKnowledge(bean, question.getId());
        }
        //获取试题章节
        if (withChapter) {
            getQuestionChapter(bean, question.getId());
        }
        // 如果版本号为空后者超出当前最大版本，则取最新版本信息
        if (version == null || version.compareTo(question.getCurrentVersion()) >= 0) {
            version = question.getCurrentVersion();
        }
        if (!version.equals(question.getCurrentVersion())) {
            QueryWrapper qw = new QueryWrapper();
            qw.eq("question_id", question.getId());
            qw.eq("version", version);
            QuestionVersion questionVersion = this.questionVersionMapper.selectOne(qw);
            if (questionVersion == null) {
                throw new XhException("当前试题版本不存在");
            }
            QuestionVersionDetail questionVersionDetail = questionVersionDetailMapper
                    .selectById(questionVersion.getId());
            bean.setId(questionVersion.getQuestionId());
            bean.setTitle(questionVersion.getTitle());
            bean.setCurrentVersion(questionVersion.getVersion());
            bean.setType(questionVersion.getType());
            bean.setSubjectId(questionVersion.getSubjectId());
            bean.setDifficult(questionVersion.getDifficult());
            bean.setOption((JSON) JSON.parse(questionVersion.getOptionContent()));
            bean.setUseCount(question.getUseCount());
            bean.setAnswerCount(question.getAnswerCount());
            bean.setAnswerRightCount(question.getAnswerRightCount());
            bean.setAnalysis(questionVersionDetail.getAnalysis());
            bean.setExamPoint(questionVersionDetail.getExamPoint());
            bean.setAnalysisPay(questionVersionDetail.getAnalysisPay());
            bean.setRefId(question.getRefId());
        } else {
            bean.setId(question.getId());
            bean.setTitle(question.getTitle());
            bean.setCurrentVersion(question.getCurrentVersion());
            bean.setSourceFrom(question.getSourceFrom());
            bean.setType(question.getType());
            bean.setOrderNo(question.getOrderNo());
            bean.setSubjectId(question.getSubjectId());
            if (!StringUtils.isEmpty(question.getSubjectId())) {
                Dictionary subject = dictionaryService.queryByTypeAndCode("SUBJECT", question.getSubjectId());
                bean.setSubjectName(subject == null ? "" : subject.getName());
            }
            bean.setDifficult(question.getDifficult());
            bean.setGradeId(question.getGradeId());
            if (!StringUtils.isEmpty(question.getOptionContent())) {
                bean.setOption((JSON) JSON.parse(question.getOptionContent()));
                if (question.getOptionArrangements() == null) {
                    bean.setOptionNum(QuestionUtils.calculateOptionArrange(JSONObject.parseArray(question.getOptionContent(), QuestionOptionDto.class)));
                } else {
                    bean.setOptionNum(question.getOptionArrangements());
                }

            }
            bean.setUseCount(question.getUseCount());
            bean.setAnswerCount(question.getAnswerCount());
            bean.setAnswerRightCount(question.getAnswerRightCount());
            bean.setAnalysis(questionDetail == null ? null : questionDetail.getAnalysis());
            bean.setExamPoint(questionDetail == null ? null : questionDetail.getExamPoint());
            bean.setAnalysisPay(questionDetail == null ? null : questionDetail.getAnalysisPay());
            bean.setRefId(question.getRefId());
        }
        bean.setYear(question.getYearId());
        bean.setSource(question.getSource());
        bean.setQuestionNo(question.getQuestionNo());
        bean.setCategory(question.getCategory());
        bean.setStatus(question.getStatus());
        bean.setVideoPath(question.getVideoPath());
        bean.setSilentVideoPath(question.getSilentVideoPath());
        bean.setVoicePath(question.getVoicePath());
        if (withRightAnswer) {
            bean.setRightAnswer((JSON) JSON.parse(question.getRightAnswer()));
            if(question.getBasicType()!=7){
                //连线题暂不处理
                formateQuestionByType(bean);
            }

        }
        //根据菁优网获取基本试题类型，用于前端显示试题

        if (question.getType() == 888) {
            bean.setBasicQuestionType(question.getBasicType());
            bean.setBasicQuestionTypeName(question.getBasicTypeName());
        } else {
            Integer basicQuestionType = questionTypeRelationService.queryToolQuestionTypeByJyType(question.getSubjectId(), question.getType());
            if (basicQuestionType != null) {
                bean.setBasicQuestionType(basicQuestionType);
            }
        }
        // 题型不为0，说明是具体的题型，应该用菁优网的题型名称
        if (question.getType() != null) {
            QuestionTypeRelation questionTypeRelation = questionTypeRelationService.queryByJyQuestionType(question.getSubjectId(), question.getType());
            if (questionTypeRelation != null) {
                bean.setQuestionTypeName(questionTypeRelation.getJyQuestionTypeName());
                bean.setBasicQuestionTypeName(questionTypeRelation.getJyQuestionTypeName());
            }else{
                bean.setQuestionTypeName("其他");
            }
        }
        //获取子试题
        List<QuestionDto> questionChild = getQuestionChild(question.getId());
        if (!CollectionUtils.isEmpty(questionChild)) {
            questionChild = questionChild.stream().sorted(Comparator.comparing(QuestionDto::getOrderNo)).collect(Collectors.toList());
        }
        bean.setChilds(questionChild);
        bean.setCreateTime(question.getCreateTime());
        bean.setCreatorName(question.getCreatorName());
        bean.setCreatorId(question.getCreatorId());
        bean.setFailReason(question.getFailReason());

        if (bean.getBasicQuestionType() != null) {
            if (bean.getBasicQuestionType() == 1 || bean.getBasicQuestionType() == 2) {
                QuestionUtils.calculateOptionArrangements(question);
                bean.setOptionNum(question.getOptionArrangements());
            } else if (bean.getBasicQuestionType() == 9 && !CollectionUtils.isEmpty(bean.getChilds())) {
                List<QuestionDto> childs = bean.getChilds();
                for (int i = 0; i < childs.size(); i++) {
                    QuestionDto questionDto = childs.get(i);
                    List<QuestionOptionDto> rights = new ArrayList<>(1);
                    questionDto.setRightAnswer((JSON) JSON.toJSON(rights));
                    if (null != questionDto.getOption()) {
                        List<QuestionOptionDto> optionDtos = JSONObject.parseArray(questionDto.getOption().toJSONString(), QuestionOptionDto.class);
                        if (question.getOptionArrangements() == null) {
                            questionDto.setOptionNum(QuestionUtils.calculateOptionArrangements(optionDtos));
                        } else {
                            bean.setOptionNum(question.getOptionArrangements());
                        }

                    }

                }
            } else if (bean.getBasicQuestionType() == 10 && bean.getOption() != null) {
                List<QuestionOptionDto> childs = JSONObject.parseArray(bean.getOption().toJSONString(), QuestionOptionDto.class);
                List<QuestionOptionDto> listOption = new ArrayList<>();

                for (int i = 0; i < childs.size(); i++) {
                    QuestionOptionDto questionOptionDto = childs.get(i);
                    if (question.getOptionArrangements() == null) {
                        questionOptionDto.setOptionNum(QuestionUtils.calculateOptionArrangements(questionOptionDto.getChilds()));
                    } else {
                        bean.setOptionNum(question.getOptionArrangements());
                    }

                    listOption.add(questionOptionDto);
                }
                bean.setOption((JSON) JSON.toJSON(listOption));
            }
        }
        //获取试题来源
        if (withQuestionSource) {
//            List<QuestionSource> questionSources = questionSourceService.queryQuestionSourceByQuestionId(id);
            List<QuestionSource> questionSources = questionSourceService.queryQuestionDetailSourceByQuestionId(question.getId());
            if (!CollectionUtils.isEmpty(questionSources)) {
                bean.setQuestionSources(questionSources);
            }
        }
        //获取试题章节知识点关系
        if (withChapterKnowledge) {
            List<QuestionChapterKnowledgeDTO> dtos = questionChapterKnowledgeService.queryByQuestionId(question.getId());
            bean.setChapterKnowles(dtos);
        }
        return bean;
    }
    @Override
    public List<QuestionDto> getQuestionChild(String questionId) {
        List<Question> childrens = getQuestionByParentId(questionId);
        if (CollectionUtils.isEmpty(childrens)) {
            return null;
        }
        List<QuestionDto> questionDtos = new ArrayList<>();
        for (Question children : childrens) {
            QuestionDetail questionDetail = questionDetailMapper.selectById(children.getId());

            QuestionDto bean = new QuestionDto();
            bean.setId(children.getId());
            bean.setTitle(children.getTitle());
            bean.setCurrentVersion(children.getCurrentVersion());
            bean.setType(children.getType());
            bean.setOrderNo(children.getOrderNo());
            bean.setSubjectId(children.getSubjectId());
            bean.setDifficult(children.getDifficult());
            bean.setGradeId(children.getGradeId());
            bean.setOption((JSON) JSON.parse(children.getOptionContent()));
            bean.setUseCount(children.getUseCount());
            bean.setAnswerCount(children.getAnswerCount());
            bean.setAnswerRightCount(children.getAnswerRightCount());
            bean.setAnalysis(questionDetail == null ? null : questionDetail.getAnalysis());
            bean.setExamPoint(questionDetail == null ? null : questionDetail.getExamPoint());
            bean.setAnalysisPay(questionDetail == null ? null : questionDetail.getAnalysisPay());
            bean.setRefId(children.getRefId());
            bean.setRightAnswer((JSON) JSON.parse(children.getRightAnswer()));
            bean.setBasicQuestionType(children.getType());

            questionDtos.add(bean);

            List<QuestionDto> questionChild = getQuestionChild(children.getId());
            if (!CollectionUtils.isEmpty(questionChild)) {
                bean.setChilds(questionChild);
            }
        }
        return questionDtos;
    }

    public List<Question> getQuestionByParentId(String questionId) {
        QueryWrapper<Question> qw = new QueryWrapper<>();
        qw.eq("parent_id", questionId);
        qw.orderByAsc("order_no");
        List<Question> questions = this.dao.selectList(qw);
        return questions;
    }

    @Override
    public XhPage queryQuestionPage(XhPage page, QuestionQueryRequest bean) throws Exception {
        // 查询个人库
        if (bean.getDataType() == 3) {
            bean.setCreatorId(UserUtils.getCurrentUserId());
        }
        bean.setQuestionSourceVal();
        //是否包含试题来源条件
        if (bean.getQuestionSource() != null && bean.getQuestionSource().hasVal()) {
            bean.setHasQuesSourceCondition(1);
        } else {
            bean.setHasQuesSourceCondition(0);
        }
        XhPage<QuestionDto> questionDtoXhPage = this.dao.queryQuestionByPage(page, bean);
        List<QuestionDto> questionDtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(questionDtoXhPage.getRecords())) {
            long time = System.currentTimeMillis();
            for (QuestionDto dto : (List<QuestionDto>) questionDtoXhPage.getRecords()) {
                QuestionDto ques = getQuestion(dto.getId(), null, true,
                        true, false, false, false);
                questionDtos.add(ques);
            }
            System.out.println("搜题时间：" + (System.currentTimeMillis() - time));
            questionDtoXhPage.setRecords(questionDtos);
        }
        return questionDtoXhPage;
    }

    private void formateQuestionByType(QuestionDto dto) {

        if (null != dto.getOption() && null != dto.getRightAnswer()) {
            dto.getBasicQuestionType();
            List<QuestionOptionDto> optionDtos = JSONObject.parseArray(dto.getOption().toJSONString(), QuestionOptionDto.class);
            List<QuestionOptionDto> rightDtos = JSONObject.parseArray(dto.getRightAnswer().toJSONString(), QuestionOptionDto.class);
            for (QuestionOptionDto rightDto : rightDtos) {
                Integer rightNo = rightDto.getNo();
                for (QuestionOptionDto optionDto : optionDtos) {
                    Integer opNo = optionDto.getNo();
                    if (rightNo == opNo) {
                        optionDto.setRight(true);
                        break;
                    }
                }
            }
            dto.setOption((JSON) JSON.toJSON(optionDtos));
        }

    }

    @Override
    public QuestionDto formatQuestion(QuestionDto dto) {
        List<QuestionDto> questionChild = getQuestionChild(dto.getId());
        if (!CollectionUtils.isEmpty(questionChild)) {
            dto.setChilds(questionChild);
        }
        if (StringUtils.isEmpty(dto.getQuestionTypeName())) {
            // 题型不为0，说明是具体的题型，应该用菁优网的题型名称
            if (dto.getType() != 0) {
                QuestionTypeRelation questionTypeRelation = questionTypeRelationService.queryByJyQuestionType(dto.getSubjectId(), dto.getType());
                if (questionTypeRelation != null) {
                    dto.setQuestionTypeName(questionTypeRelation.getJyQuestionTypeName());
                }
            } else {
                dto.setQuestionTypeName(dto.getBasicQuestionTypeName());
            }
        }
        if (!StringUtils.isEmpty(dto.getOptionContent())) {
            dto.setOption((JSON) JSON.parse(dto.getOptionContent()));

            dto.setOptionNum(QuestionUtils.calculateOptionArrange(JSONObject.parseArray(dto.getOptionContent(), QuestionOptionDto.class)));
            dto.setOptionContent(null);
        }
        //判断题选项删除
        if (dto.getBasicQuestionType() != null && dto.getBasicQuestionType() == 4) {
            dto.setOption(null);
        }
        if (!StringUtils.isEmpty(dto.getRightAnswerContent())) {
            dto.setRightAnswer((JSON) JSON.parse(dto.getRightAnswerContent()));
            dto.setRightAnswerContent(null);
        }
        QuestionDto question = getQuestion(dto.getId(), null);
        if (null != question) {
            dto.setAnalysis(question.getAnalysis());
        }

        QuestionCollectRequest bean = new QuestionCollectRequest();
        bean.setQuestionId(dto.getId());
        bean.setUserId(UserUtils.getCurrentUserId());
        List<QuestionCollect> collectList = questionCollectService.queryQuestionCollect(bean);
        dto.setIsCollect(collectList.size() > 0);
        return dto;
    }

    @Override
    public Question queryByMd5AndSubject(String md5, String subjectId) {
        if (StringUtils.isEmpty(md5) && StringUtils.isEmpty(subjectId)) {
            return null;
        }
        QueryWrapper<Question> qw = new QueryWrapper<>();
        if (!StringUtils.isEmpty(md5)) {
            qw.eq("question_md5", md5);
        }
        if (!StringUtils.isEmpty(subjectId)) {
            qw.eq("subject_id", subjectId);
        }
        List<Question> questions = this.dao.selectList(qw);
        if (!CollectionUtils.isEmpty(questions)) {
            return questions.get(0);
        }
        return null;
    }

    @Override
    public List queryQuestion(QuestionQueryRequest bean) {
        List<QuestionDto> result = new ArrayList<>();
        for (int i = 0; i < bean.getIds().length; i++) {
            String id = bean.getIds()[i];
            result.add(getQuestion(id, null, true, false, false, false, false));
        }
        return result;
    }

    @Override
    public List<String> queryQuesitonRandom(QuestionQueryRequest bean) {
        if (bean.getRandomCount() == null || bean.getRandomCount() <= 0) {
            bean.setRandomCount(10);
        }
        if (bean.getRandomCount() > 1000) {
            bean.setRandomCount(1000);
        }

        bean.setRandomFetchSize(bean.getRandomCount() * 10);

        Integer totalCount = this.dao.queryRandomQuestionsCount(bean);
        //TODO  当小于总数时，从0开始获取
        if (totalCount <= bean.getRandomCount()) {
            bean.setRandomStart(0);
        }
//        }else {
//            bean.setRandomStart(RandomUtils.nextInt(1, totalCount - bean.getRandomCount() + 2));
//        }
        List<String> result = this.dao.queryRandomQuestions(bean);
        if (result.size() < bean.getRandomCount()) {
            return result;
        } else {
            List<String> randomResult = new ArrayList<>();
            for (int i = 0; i < bean.getRandomCount(); i++) {
                int index = RandomUtils.nextInt(0, result.size());
                randomResult.add(result.get(index));
                result.remove(index);
            }
            return randomResult;
        }
    }

    @Override
    public List<QuestionDto> importWordQuestions(String path, HttpServletRequest reqeust) {
        if (StringUtils.isEmpty(path)) {
            throw new XhException("路径不能为空");
        }
        String outPath = FileUtils.getUploadRootPath(reqeust);
        String filename = FileUtils.createRandomFilename() + "." + FileUtils.getExt(path);

        String uploadPath = reqeust.getSession().getServletContext().getRealPath("/");

        if (path.startsWith("http://") || path.startsWith("https://")) {
            // 下载文件
            path = FileUtils.downloadFile(path, filename, outPath);
        } else {
            path = uploadPath + path;
        }

        OfficeUtils.word2html(path, path + ".html", null);
        String html = "";
        try {
            html = org.apache.commons.io.FileUtils.readFileToString(new File(path + ".html"), "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<QuestionDto> list = QuestionUtils.analysisQuestionsFromHtml(html);
        // 获取错误信息
        String errorMsg = getErrorMsg(list);
        String questionIds = null;
        if (StringUtils.isEmpty(errorMsg)) {
            // 将题目插入数据库
            questionIds = saveQuestion(list, new ArrayList<>());
        }
        // 插入导入记录
        QuestionImportLog importLog = new QuestionImportLog();
        importLog.setFailReason(errorMsg);
        importLog.setFileName(FileUtils.getFileName(path));
        importLog.setQuestionIds(questionIds);
        if (StringUtils.isEmpty(errorMsg)) {
            importLog.setStatus(2);
        }
        questionImportLogService.insert(importLog);
        return list;
    }

    private String getErrorMsg(List<QuestionDto> list) {
        StringBuffer errorMsg = new StringBuffer("");
        for (QuestionDto dto : list) {
            if (!dto.getDataRight()) {
                errorMsg.append(dto.getDataErrorMsg());
                errorMsg.append(";");
                continue;
            }
        }
        return errorMsg.toString();
    }

    private String saveQuestion(List<QuestionDto> list, List<ImportQuestionErrorLog> quesErrorLogs) {

        List<Question> questionList = new ArrayList<Question>();
        List<QuestionDetail> questionDetailList = new ArrayList<QuestionDetail>();

        for (int i = 0; i < list.size(); i++) {
            QuestionDto dto = list.get(i);
            Question question = new Question();
            question.setTitle(dto.getTitle());
            question.setType(dto.getType());
            question.setSubjectId(dto.getSubjectId());
            question.setCurrentVersion(1);
            question.setQuestionNo(dto.getQuestionNo());
            //来源：1自建：2：word导入 3 批量导入
//            question.setSource("2");
            question.setSourceFrom(3);
            question.setOptionContent(dto.getOption() == null ? "" : dto.getOption().toJSONString());
//			question.setKnowledgeIds(dto.getKnowledgePoints());
            question.setRightAnswer(dto.getRightAnswer() == null ? "" : dto.getRightAnswer().toJSONString());
            question.setSubjectId(dto.getSubjectId());
            question.setQuestionMd5(question.genarateMd5());
            question.setDifficult(dto.getDifficult());
            question.setGradeId(dto.getGradeId());
            question.setStatus(dto.getStatus());
            question.setFailReason(dto.getFailReason());
            question.setBasicType(dto.getBasicQuestionType());
            question.setBasicTypeName(dto.getBasicQuestionTypeName());

            QuestionUtils.calculateOptionArrangements(question);

//            //重复试题查询
//            Question existsQues = queryByMd5AndSubject(question.genarateMd5(), question.getSubjectId());
//            if (existsQues != null) {
//                String existsMsg = "第" + j + "道试题已存在！请删除后再进行录入";
//                existMsgList[j - 1] = existsMsg;
//            }
//            j++;
            //存在重复试题保存试题
//            if (!CollectionUtils.isEmpty(existMsgList)) {
//                continue;
//            }
            this.dao.insert(question);

            // 题目详情
            QuestionDetail questionDetail = new QuestionDetail();
            questionDetail.setId(question.getId());
            questionDetail.setAnalysis(dto.getAnalysis());
            questionDetail.setExamPoint(dto.getExamPoint());
            questionDetail.setAnalysisPay(dto.getAnalysisPay());
            questionDetail.setAnalysisVideo(dto.getAnalysisVideo());

            questionDetailMapper.insert(questionDetail);

            if (!CollectionUtils.isEmpty(dto.getChilds())) {
                if (!CollectionUtils.isEmpty(dto.getChilds())) {
                    //todo 添加子试题
                    dto.setId(question.getId());
                    saveChildrenQuestion(dto, dto.getChilds());
                }
            }

            if (!StringUtils.isEmpty(dto.getDataErrorMsg())) {
                ImportQuestionErrorLog log = new ImportQuestionErrorLog();
                log.setQuestionErrorReason(dto.getDataErrorMsg());
                log.setQuestionNo((i + 1));
                log.setQuestionId(question.getId());
                quesErrorLogs.add(log);
            }
            questionList.add(question);
            questionDetailList.add(questionDetail);

        }
//        if (!CollectionUtils.isEmpty(existMsgList)) {
//            throw new XhException(existMsgList.stream().collect(Collectors.joining("；")));
//        }
        return questionList.stream().map(item -> item.getId()).collect(Collectors.joining(","));
    }

    private String saveQuestion2Temp(List<QuestionDto> list) {

        List<Question> questionList = new ArrayList<Question>();
        List<QuestionDetail> questionDetailList = new ArrayList<QuestionDetail>();

        List<String> existMsgList = new ArrayList<>();
        int j = 1;
        for (QuestionDto dto : list) {
            Question question = new Question();
            question.setTitle(dto.getTitle());
            question.setType(dto.getType());
            question.setSubjectId(dto.getSubjectId());
            question.setCurrentVersion(1);
            //来源：1自建：2：word导入
            question.setSource("2");
            question.setSourceFrom(1);
            question.setOptionContent(dto.getOption() == null ? "" : dto.getOption().toJSONString());
//			question.setKnowledgeIds(dto.getKnowledgePoints());
            question.setRightAnswer(dto.getRightAnswer() == null ? "" : dto.getRightAnswer().toJSONString());
            question.setSubjectId(dto.getSubjectId());
            question.setQuestionMd5(question.genarateMd5());
            question.setDifficult(dto.getDifficult());
            question.setGradeId(dto.getGradeId());
            question.setStatus(dto.getStatus());
            QuestionUtils.calculateOptionArrangements(question);

            //重复试题查询
            Question existsQues = queryByMd5AndSubject(question.genarateMd5(), question.getSubjectId());
            if (existsQues != null) {
                String existsMsg = "第" + j + "道试题已存在！请删除后再进行录入";
                existMsgList.add(existsMsg);
            }
            j++;
            //存在重复试题保存试题
//            if (!CollectionUtils.isEmpty(existMsgList)) {
//                continue;
//            }
            QuestionCopy questionCopy = new QuestionCopy();
            BeanUtils.copyProperties(question, questionCopy);
            questionCopyMapper.insert(questionCopy);

            // 题目详情
            QuestionDetail questionDetail = new QuestionDetail();
            questionDetail.setId(question.getId());
            questionDetail.setAnalysis(dto.getAnalysis());
            questionDetail.setExamPoint(dto.getExamPoint());
            questionDetail.setAnalysisPay(dto.getAnalysisPay());
            questionDetail.setAnalysisVideo(dto.getAnalysisVideo());

            questionDetailMapper.insert(questionDetail);

            if (!CollectionUtils.isEmpty(dto.getChilds())) {
                if (!CollectionUtils.isEmpty(dto.getChilds())) {
                    //todo 添加子试题
                    dto.setId(question.getId());
                    saveChildrenQuestion(dto, dto.getChilds());
                }
            }
            questionList.add(question);

            questionDetailList.add(questionDetail);

        }
        if (!CollectionUtils.isEmpty(existMsgList)) {
            throw new XhException(existMsgList.stream().collect(Collectors.joining("；")));
        }

        String questionIds = "";
        Map<String, String> questionRepeat = new HashMap<>(16);
        for (int i = 0; i < questionList.size(); i++) {
            Question question = questionList.get(i);
            String questionId = question.getId();
            questionIds += questionId;
            questionIds += ",";
            //查询是否重复率到80%
            List<Map> questions = elasticSearchService.termQuery("title", HtmlUtils.delHTMLTag(question.getTitle() + question.getOptionContent()), TikuEsContant.ES_INDEX_TIKU,
                    TikuEsContant.TYPE.ES_INDEX_TYPE_QUESTION, Map.class);
//             questions.stream().filter(map -> MapUtils.getDouble(map, "_sorce") > 0.8).collect(Collectors.toList());

//            addQuestion2ES(question);
        }
        questionRepeat.put("questionIds", questionIds);
        return questionIds;
    }

    @Override
    public void initQuestionData() {
        String ino = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        XhPage page = new XhPage<>();
        page.setSize(10000);
        do {
            page = this.dao.queryInitData(page);
            for (Object obj : page.getRecords()) {
                try {
                    Map<String, Object> item = (Map<String, Object>) obj;
                    String id = item.get("id").toString();
                    List<Map<String, Object>> optionsSrc = this.dao.queryQuestionOptions(id);
                    // [{no:1,content:''},{no:2,content:''}]
                    JSONArray options = new JSONArray();
                    for (Map<String, Object> optionSrc : optionsSrc) {
                        String optionNum = optionSrc.get("option_num").toString().trim().toUpperCase();
                        String optionContent = optionSrc.get("content") == null ? ""
                                : optionSrc.get("content").toString();
                        JSONObject option = new JSONObject();
                        option.put("no", ino.indexOf(optionNum) + 1);
                        option.put("content", optionContent);
                        options.add(option);
                    }

                    Question question = this.dao.selectById(id);
                    question.setOptionContent(options.toJSONString());
                    question.setQuestionMd5(question.genarateMd5());
                    this.dao.updateById(question);
                    System.out.println(item.get("optionNums"));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }

        } while (page.hasNext());

    }

    @Override
    public void downloadQuestionDataRes() {
        XhPage page = new XhPage<>();
        page.setSize(5000);
        QueryWrapper qw = new QueryWrapper();
        qw.eq("deleted", 0);
        qw.isNull("question_md5");
        do {
            page = (XhPage) this.dao.selectPage(page, qw);

            ExecutorService executorService = Executors.newCachedThreadPool();
            final Semaphore semaphore = new Semaphore(50);
            final CountDownLatch countDownLatch = new CountDownLatch((int) page.getSize());

            for (Object obj : page.getRecords()) {
                // executorService.execute(() -> {
                // try {
                // semaphore.acquire();
                try {
                    StringBuffer sb = new StringBuffer();
                    Question question = (Question) obj;
                    question.setTitle(changeUrlHost(question.getId(), question.getTitle()));

                    QuestionDetail questionDetail = this.questionDetailMapper.selectById(question.getId());
                    if (questionDetail != null) {
                        questionDetail.setAnalysis(changeUrlHost(question.getId(), questionDetail.getAnalysis()));
                        questionDetail.setExamPoint(changeUrlHost(question.getId(), questionDetail.getExamPoint()));
                        try {
                            this.questionDetailMapper.updateById(questionDetail);
                        } catch (Exception ex) {

                        }
                    }

                    if (question.getType() == 1 || question.getType() == 2) {
                        JSONArray options = JSONArray.parseArray(question.getOptionContent());
                        if (options == null) {
                            return;
                        }
                        for (int i = 0; i < options.size(); i++) {
                            JSONObject option = options.getJSONObject(i);
                            option.replace("content", changeUrlHost(question.getId(), option.getString("content")));
                        }
                        question.setOptionContent(options.toJSONString());
                    }
                    if (question.getType() == 3) {
                        JSONArray options = JSONArray.parseArray(question.getRightAnswer());
                        if (options == null) {
                            return;
                        }
                        for (int i = 0; i < options.size(); i++) {
                            JSONObject option = options.getJSONObject(i);
                            option.replace("content", changeUrlHost(question.getId(), option.getString("content")));
                        }
                        question.setRightAnswer(options.toJSONString());
                    } else if (question.getType() == 5) {
                        JSONObject rightAnswer = new JSONObject();
                        rightAnswer.put("content", changeUrlHost(question.getId(), question.getRightAnswer()));
                        question.setRightAnswer(rightAnswer.toJSONString());
                    }
                    question.setQuestionMd5(question.genarateMd5());
                    try {
                        this.dao.updateById(question);
                    } catch (Exception ex) {

                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                }
                // semaphore.release();
                // } catch (Exception e) {
                // e.printStackTrace();
                // }
                // countDownLatch.countDown();
                // });
            }

            // try {
            // countDownLatch.await();
            // } catch (InterruptedException e) {
            // e.printStackTrace();
            // }
            // executorService.shutdown();

        } while (page.hasNext());
    }

    private String changeUrlHost(String questionId, String source) {
        if (StringUtils.isEmpty(source)) {
            return source;
        }
        String result = "";
        Document doc = Jsoup.parse(source);
        doc.outputSettings().prettyPrint(false);
        Elements resList = doc.select("img,video,audio");
        for (Object o : resList) {// HtmlAgilityPack.HtmlNode
            // paraNode=paraList[3];
            if (o instanceof Element) {
                Element paraNode = (Element) o;
                paraNode.attr("src", replaceUrlHost(questionId, paraNode.attr("src")));
            }

            // Debug.WriteLine("");
        }
        result = doc.body().html();
        return result;
    }

    private String replaceUrlHost(String questionId, String url) {
        if (url.contains("cdn.tiku.xiaohe.com") || url.startsWith("data")) {
            return url;
        }
        String host = "";
        String filename = "";
        String outpath = "/Users/david/Documents/questionImage/";
        String savePath = "";
        try {

            org.apache.commons.io.FileUtils.writeStringToFile(new File("/Users/david/question_res_url.txt"),
                    url + "\r\n", true);
            host = StringUtils.getUrlHost(url);
            outpath += MD5Utils.string2MD5(host);

            filename = MD5Utils.string2MD5(url);

            String ext = "";
            ext = url.substring(url.lastIndexOf('.'));
            ext = ext.length() > 4 ? ".png" : ext;

            filename += ext.toLowerCase();

            savePath = FileUtils.downloadFile(url, filename, outpath);
        } catch (Exception e) {
            e.printStackTrace();
        }

        QuestionUrlDownload questionUrlDownload = new QuestionUrlDownload();
        questionUrlDownload.setQuestionId(questionId);
        questionUrlDownload.setOldUrl(url);
        questionUrlDownload.setNewUrl("http://cdn.tiku.xiaohe.com/" + MD5Utils.string2MD5(host) + "/" + filename);

        if (!StringUtils.isEmpty(savePath)) {
            questionUrlDownload.setStatus(1);
        } else {
            questionUrlDownload.setStatus(0);
        }
        this.questionUrlDownloadMapper.insert(questionUrlDownload);
        // String prtocal=url.startsWith("https")?"https://":"http://";
        // String newHost="cdn.tiku.xiaohe.com/";
        // String result=url.replaceAll("^http(s)?:\\/\\/(.*?)\\/",newHost);
        // prtocal+result

        return questionUrlDownload.getStatus() == 1 ? questionUrlDownload.getNewUrl() : questionUrlDownload.getOldUrl();
    }

    /**
     * 准备条件
     *
     * @param bean
     * @param qw
     */
    private QueryWrapper prepareParams(QuestionQueryRequest bean, QueryWrapper qw) {
        if (bean.getIds() != null && bean.getIds().length > 0) {
            qw.in("id", bean.getIds());
        }
        if (CollectionUtils.isEmpty(bean.getSubjectIds())) {
            qw.in("subject_id", bean.getSubjectIds());
        }
        return qw;
    }

    @Override
    public List<QuestionDto> queryFromJY(String subject, List<String> ids) throws Exception {
        // 先查询本地库中存不存在
        QueryWrapper<Question> qw = new QueryWrapper<Question>();
        qw.in("ref_id", ids);
        List<QuestionDto> exist = super.selectList(qw, QuestionDto.class);
        for (QuestionDto q : exist) {
            ids.remove(q.getRefId());
        }
        // 获取所选学科的试题解析（分析、解答、点评、考点、专题等）
        List<QuestionDetail> details = new ArrayList<QuestionDetail>();
        for (String id : ids) {
            QuestionDto dto = jyquestionService.queryAnalyze(subject, id);
            System.out.println("saveQuestion：id" + id + "subject" + subject + JSON.toJSONString(dto));
            QuestionDetail detail = new QuestionDetail();
            detail.setId(id);
            detail.setAnalysis(dto.getAnalysis());
            details.add(detail);
            addQuestion(dto);
            exist.add(dto);
        }
        questionDetailService.batchInsert(details);
        return exist;

    }

    /**
     * 先按照题目的知识点查询题目，再查相似题
     *
     * @param page
     * @param bean
     * @return
     * @throws Exception
     */
    @Override
    public XhPage<QuestionDto> querySimilar(XhPage page, QuestionQueryRequest bean) throws Exception {
//        page = queryQuestionPage(page, bean);
//		if(page.getRecords().size()<page.getSize()){
//			//TODO:查询菁优网
//			//page.setRecords(QuestionRequest.queryRecommond(bean.getSubject(), bean.getId(), page.getSize()));
//			//page = QuestionRequest.queryByParam(bean.getSubject(), bean.getSearchType(), bean.getFirstKnowledge(), bean.getSecondKnowledge(), bean.getKnowledgePoints(), bean.getTypes(), bean.getDifficults(), 
//					//bean.getRegions(), bean.getSources(), bean.getYears(), bean.getOrder(), bean.getOrderType(), page);
//		}
//		QuestionRequest.querySimilar();
        QuestionDto question = getQuestion(bean.getId(), null);

        QuestionKnowledgeRequest questionKnowledgeRequest = new QuestionKnowledgeRequest();
        questionKnowledgeRequest.setQuestionId(question.getId());
        List<String> knowledgePoints = null;
        List<QuestionKnowledge> questionKnowledges = questionKnowledgeService.queryQuestionKnowledge(questionKnowledgeRequest);
        if (!CollectionUtils.isEmpty(questionKnowledges)) {
            knowledgePoints = questionKnowledges.stream().map(item -> item.getKnowledgeId()).collect(Collectors.toList());
        }

        XhPage<QuestionDto> questionDtoXhPage = new XhPage<>();
        List<QuestionDto> datas = new ArrayList<>();
        if (!CollectionUtils.isEmpty(knowledgePoints)) {
            QuestionQueryRequest queryQuestionRequest = new QuestionQueryRequest();
            queryQuestionRequest.setType(question.getType());
            queryQuestionRequest.setSubject(question.getSubjectId());
            queryQuestionRequest.setKnowledgePoints(knowledgePoints);

            questionDtoXhPage = this.dao.queryByPage(page, queryQuestionRequest);

            for (QuestionDto dto : (List<QuestionDto>) questionDtoXhPage.getRecords()) {
                QuestionDto ques = getQuestion(dto.getId(), null, true, true, false, false, false);
                datas.add(ques);
            }
        }

        if (CollectionUtils.isEmpty(datas)) {
            List<Question> questions = elasticSearchService.matchQuery("title", HtmlUtils.delHTMLTag(question.getTitle() + question.getOptionContent()), TikuEsContant.ES_INDEX_TIKU, TikuEsContant.TYPE.ES_INDEX_TYPE_QUESTION, Question.class);
            if (CollectionUtils.isEmpty(questions)) {
                return new XhPage<>();
            }
            String[] ids = questions.stream().map(Question::getId).toArray(String[]::new);
            QuestionQueryRequest queryQuestionRequest = new QuestionQueryRequest();
            queryQuestionRequest.setIds(ids);
            queryQuestionRequest.setType(question.getType());
            queryQuestionRequest.setSubject(question.getSubjectId());

            questionDtoXhPage = this.dao.queryByPage(page, queryQuestionRequest);

            for (QuestionDto dto : (List<QuestionDto>) questionDtoXhPage.getRecords()) {
                QuestionDto ques = getQuestion(dto.getId(), null, true, true, false, false, false);
                datas.add(ques);
            }
        }

        questionDtoXhPage.setRecords(datas);
        return questionDtoXhPage;
    }


    @Override
    public List<QuestionDto> queryVariant(List<QuestionVariantRequest> beans) throws Exception {
        List<QuestionDto> all = new ArrayList<QuestionDto>();
        for (QuestionVariantRequest bean : beans) {
            XhPage<QuestionDto> page = new XhPage<QuestionDto>();
            page.setCurrent(1);
            page.setSize(2);
            List<String> ids = new ArrayList<>();
            if (!CollectionUtils.isEmpty(bean.getKnowledgePoints())) {
                Knowledge knowledge = bean.getKnowledgePoints().get(0);
                List<String> knowledgeNos = eachGetKnowledgeNoById(knowledge.getId(), new ArrayList<>());
                if (!CollectionUtils.isEmpty(knowledgeNos)) {
                    for (int i = knowledgeNos.size() - 1; i >= 0; i--) {
                        ids.add(knowledgeNos.get(i));
                    }
                }
                System.out.println(1);
            }
            List<QuestionDto> list = list = jyquestionService.queryByParam(bean.getSubject(), 2, bean.getBookVersionId(), bean.getBookChapterId(), ids, bean.getType(), bean.getDifficult(),
                    0, "", "0", "0", 0, 0, 0, page).getRecords();
            if (!CollectionUtils.isEmpty(list)) {
                QuestionDto questionDto = list.get(0);
                //判断变式题是否为传过来的试题
                if (questionDto.getId().equals(bean.getQuestionId())) {
                    list.remove(0);
                    if (!CollectionUtils.isEmpty(list)) {
                        all.add(list.get(0));
                    }
                } else {
                    all.add(list.get(0));
                }
            }
        }
        return all;
    }


    List<String> eachGetKnowledgeNoById(String knowledgeId, List<String> knowledgeNos) {
        Knowledge knowledge = knowledgeService.getById(knowledgeId);
        if (knowledge != null) {
            knowledgeNos.add(knowledge.getNo());
            if (!StringUtils.isEmpty(knowledge.getParentId())) {
                eachGetKnowledgeNoById(knowledge.getParentId(), knowledgeNos);
            }
        }
        return knowledgeNos;
    }


    @Override
    public QuestionDto addQuestion(QuestionDto bean) {
        Question byId = this.getById(bean.getId());
        if (byId != null) {
            return bean;
        }
        Question question = new Question();
        question.setId(bean.getId());
        question.init();
        question.setBasicType(bean.getBasicQuestionType());
        question.setBasicTypeName(bean.getBasicQuestionTypeName());
        question.setRefId(bean.getRefId());
        question.setTitle(bean.getTitle());
        question.setType(bean.getType());
        question.setSubjectId(bean.getSubjectId());
        question.setDifficult(bean.getDifficult());
        question.setGradeId(bean.getGradeId());
        if (bean.getOption() != null) {
            question.setOptionContent(bean.getOption().toJSONString());
        }
        if (bean.getRightAnswer() != null) {
            question.setRightAnswer(bean.getRightAnswer().toJSONString());
        }
        question.setQuestionMd5(question.genarateMd5());

        Question existsQues = this.queryByMd5AndSubject(question.getQuestionMd5(), question.getSubjectId());
        if (existsQues != null) {
            bean.setId(existsQues.getId());
        } else {
            // 计算选项的排列方式
            QuestionUtils.calculateOptionArrangements(question);
            this.insert(question);
            //返回本地题库id
            bean.setId(question.getId());

            QuestionDetail questionDetail = new QuestionDetail();
            questionDetail.setId(question.getId());
            questionDetail.setAnalysis(bean.getAnalysis());
            questionDetail.setExamPoint(bean.getExamPoint());
            questionDetail.setAnalysisPay(bean.getAnalysisPay());
            questionDetail.setAnalysisVideo(bean.getAnalysisVideo());
            questionDetailMapper.insert(questionDetail);
            //子试题
            if (!CollectionUtils.isEmpty(bean.getChilds())) {
                if (!CollectionUtils.isEmpty(bean.getChilds())) {
                    //直接删除子试题
                    QueryWrapper qw = new QueryWrapper();
                    qw.eq("parent_id", question.getId());
                    this.deleteByCondition(qw);
                    //添加子试题
                    bean.setId(question.getId());
                    saveChildrenQuestion(bean, bean.getChilds());
                }
            }
            if (!CollectionUtils.isEmpty(bean.getKnowledges())) {
                List<String> knowledgeIds = new ArrayList<String>();
                bean.getKnowledges().forEach(knowledge -> {
                    knowledgeIds.add(knowledge.getId());
                });
                // 增加题目和知识点关联
                addQuestionKnowledge(knowledgeIds, question);
            }

            if (!CollectionUtils.isEmpty(bean.getChaptersIds())) {
                bean.getChaptersIds().forEach(item -> {
                    QuestionChapterKnowledge questionChapterKnowledge = new QuestionChapterKnowledge();
                    questionChapterKnowledge.setChapterId(item);
                    questionChapterKnowledge.setQuestionId(question.getId());
                    questionChapterKnowledgeService.insert(questionChapterKnowledge);
                });

            }
            //试题来源
            if (!CollectionUtils.isEmpty(bean.getQuestionSources())) {
                for (int i = 0; i < bean.getQuestionSources().size(); i++) {
                    QuestionSource questionSource = bean.getQuestionSources().get(i);
                    questionSource.setQuestionId(question.getId());
                    questionSource.setOrderNo((i + 1));
                    questionSourceService.insert(questionSource);
                }
            }
            // 添加索引到es
//            addQuestion2ES(question);
        }
        return bean;
    }

    @Override
    public Question queryByRefId(String refId) {
        QueryWrapper qw = new QueryWrapper();
        qw.eq("ref_id", refId);
        return this.dao.selectOne(qw);
    }

    @Override
    public String downloadQuestion(Integer downloadType, String subjectId, String quesId, HttpServletRequest request) throws Exception {
        String savePath = request.getSession().getServletContext().getRealPath("") + "jyQuestionFile" + File.separator + downloadType + File.separator + quesId + ".doc";

        File file = new File(savePath);
        //如果文件存在直接返回路径
        if (file.exists()) {
            return savePath;
        }
        File dir = file.getParentFile();
        if (!dir.exists()) {//判断文件目录是否存在
            dir.mkdirs();
        }
        System.out.println(savePath);
        Integer method = 3;
        //下载学生版不需要答案和解析
        if (downloadType.equals(2)) {
            method = 0;
        }
        byte[] bytes = jyquestionService.downloadQuestion(subjectId, quesId, method, 1);
        FileUtils.saveFile(bytes, savePath);
        return savePath;
    }

    @Override
    public QuestionImportLog importQuestion(String subjectId, String subjectName, String path, String fileName, Integer schoolId, HttpServletRequest request) {
        if (StringUtils.isEmpty(path)) {
            throw new XhException("路径不能为空");
        }
        String outPath = FileUtils.getUploadRootPath(request);
        String filename = FileUtils.createRandomFilename() + "." + FileUtils.getExt(path);

        String uploadPath = request.getSession().getServletContext().getRealPath("/");

        if (path.startsWith("http://") || path.startsWith("https://")) {
            // 下载文件
            path = FileUtils.downloadFile(path, filename, outPath);
        } else {
            path = uploadPath + path;
        }
        List<Map<String, Object>> relationMap = questionTypeRelationService.queryRelationMapBySubject(subjectId);
        List<QuestionDTO> parse = com.xh.tools.question.util.QuestionUtils.parse(path, relationMap);

        if (CollectionUtils.isEmpty(parse)) {
            throw new XhException("未检测到试题");
        }
        List<QuestionDto> allQuestionDtoList = new ArrayList<>();
        //检验试题是否合法
        List<ImportQuestionErrorLog> quesErrorLogs = new ArrayList<>();
        List<String> errMsgList = new ArrayList<>();
        for (int i = 0; i < parse.size(); i++) {
            String errorMsg = "";
            QuestionDTO questionDTO = parse.get(i);
            if (!CollectionUtils.isEmpty(questionDTO.getDataErrorMsg())) {
                errorMsg = questionDTO.getDataErrorMsg().stream().collect(Collectors.joining(","));
            }
            questionDTO.setSubjectId(subjectId);
            QuestionDto questionDto = converQuestion(questionDTO);

            //根据试题类型名称获取具体试题类型
            QuestionTypeRelation typeRelation = questionTypeRelationService.queryByJyQuesTypeName(subjectId, questionDTO.getTypeName());
            if (typeRelation != null) {
                questionDto.setType(typeRelation.getJyQuestionType());
                questionDto.setBasicQuestionType(typeRelation.getToolQuestionType());
                questionDto.setBasicQuestionTypeName(typeRelation.getToolQuestionTypeName());
            } else {
                //其他题型
                questionDto.setType(QuestionTypeEnum.OTHER.getValue());
                questionDto.setBasicQuestionType(questionDTO.getType());
                questionDto.setBasicQuestionTypeName(questionDTO.getTypeName());
                if (StringUtils.isEmpty(errorMsg)) {
                    errorMsg = "题型未匹配";
                } else {
                    errorMsg += ";题型未匹配";
                }
            }

            questionDto.setStatus(-1);
            questionDto.setSubjectName(subjectName);
            questionDto.setDataRight(questionDTO.getDataRight());
            questionDto.setFailReason(questionDTO.getDataErrorMsg().stream().collect(Collectors.joining(",")));

            if (!StringUtils.isEmpty(errorMsg)) {
                questionDto.setDataErrorMsg(errorMsg);
                errMsgList.add("第" + (i + 1) + "题：" + errorMsg);
            }
            allQuestionDtoList.add(questionDto);
        }
        // 获取错误信息
        String questionIds = null;
        // 将题目插入数据库
        try {
            questionIds = saveQuestion(allQuestionDtoList, quesErrorLogs);
        } catch (Exception e) {
            throw new XhException(e.getMessage());
        }
        String errorMsg = "";
        if (!CollectionUtils.isEmpty(errMsgList)) {
            errorMsg = errMsgList.stream().collect(Collectors.joining("<br>"));
        }
        // 插入导入记录
        QuestionImportLog importLog = new QuestionImportLog();
        importLog.setSubjectId(subjectId);
        importLog.setSubjectName(subjectName);
        importLog.setFailReason(errorMsg);
        importLog.setFileName(fileName);
        importLog.setFilePath(path);
        importLog.setQuestionIds(questionIds);
        importLog.setSchoolId(schoolId);
        if (StringUtils.isEmpty(errorMsg)) {
            importLog.setStatus(2);
        } else {
            importLog.setStatus(1);
        }
        questionImportLogService.insert(importLog);

        /*if (!CollectionUtils.isEmpty(quesErrorLogs)) {
            quesErrorLogs.forEach(item -> item.setImportLogId(importLog.getId()));
            importQuestionErrorLogService.batchInsert(quesErrorLogs);
        }*/
        return importLog;
    }

    @Override
    public String batchSaveQuestion(BatchSaveQuestionRequest request) {
        if (CollectionUtils.isEmpty(request.getQuestions())) {
            return "试题数据不存在";
        }
//        QuestionImportLog importLog = questionImportLogService.getById(request.getQuestionImportLogId());
//        if (importLog == null) {
//            return "导入记录不存在";
//        }
//        AreaDto areaDto = LongwenApi.queryAreaBySchoolId(importLog.getSchoolId());
        List<String> questionIds = new ArrayList<>();
        for (QuestionSaveRequest bean : request.getQuestions()) {
            Question question = this.getById(bean.getId());
            if (question == null) {
                return "当前试题ID不存在";
            }
            //格式化题目
            QuestionDTO questionDTO = com.xh.tools.question.util.QuestionUtils.parse(bean.getBasicQuestionType(), bean.getQuestionTypeName(), bean.getTitle(), bean.getAnswer() == null ? "" : bean.getAnswer(), bean.getAnalysis());
            String errMsg = null;
            if (!CollectionUtils.isEmpty(questionDTO.getDataErrorMsg())) {
                errMsg = questionDTO.getDataErrorMsg().stream().collect(Collectors.joining(","));
            }
            questionDTO.setSubjectId(bean.getSubjectId());
            QuestionDto dto = converQuestion(questionDTO);

            QuestionDetail questionDetail = this.questionDetailMapper.selectById(question.getId());

            // 将变动内容保存至主表
//            question.setSourceFrom(1);
            question.setTitle(dto.getTitle());
            question.setType(bean.getType());
            //获取基础题型
            QuestionTypeRelation questionType = questionTypeRelationService.queryByJyQuestionType(bean.getSubjectId(), bean.getType());
            if (questionType != null) {
                question.setBasicType(questionType.getToolQuestionType());
                question.setBasicTypeName(questionType.getToolQuestionTypeName());
            }
            question.setSubjectId(bean.getSubjectId());
            question.setDifficult(bean.getDifficult());
            question.setGradeRangeId(bean.getGradeRangeId());
            question.setGradeId(bean.getGradeId());
            question.setYearId(bean.getYear());
            question.setCategory(bean.getCategory());
            question.setSource(bean.getSource());
            question.setLabels(bean.getLabels());
            question.setFailReason(errMsg);
//            question.setSchoolId(importLog.getSchoolId().toString());
            // if (StringUtils.isEmpty(question.getFailReason())) {
            question.setStatus(3);
            //}

            if (!CollectionUtils.isEmpty(dto.getOptions())) {
                question.setOptionContent(dto.getOption() == null ? "" : dto.getOption().toJSONString());
            }
            if (null != dto.getRightAnswer()) {
                question.setRightAnswer(dto.getRightAnswer() == null ? "" : dto.getRightAnswer().toJSONString());
            } else {
                if (null != bean.getRightAnswer()) {
                    question.setRightAnswer(bean.getRightAnswer() == null ? "" : bean.getRightAnswer().toJSONString());
                }
            }
            question.setQuestionMd5(question.genarateMd5());
            if (questionDetail == null) {
                questionDetail = new QuestionDetail();
                questionDetail.setId(question.getId());
                questionDetailService.insert(questionDetail);
            }
            questionDetail.setAnalysis(dto.getAnalysis());
            questionDetail.setExamPoint(bean.getExamPoint());
            questionDetail.setAnalysisPay(bean.getAnalysisPay());
            questionDetail.setAnalysisVideo("-");

            // 试题版本号加一
            question.setCurrentVersion(question.getCurrentVersion() + 1);
            this.update(question);
            questionDetailService.update(questionDetail);

            questionSourceService.deleteQuestionSourceByQuestionId(question.getId());
            if (!CollectionUtils.isEmpty(bean.getQuestionSources())) {
                for (int i = 0; i < bean.getQuestionSources().size(); i++) {
                    QuestionSource questionSource = bean.getQuestionSources().get(i);
                    questionSource.setId(null);
                    questionSource.setQuestionId(question.getId());
                    questionSource.setOrderNo((i + 1));
                    questionSourceService.insert(questionSource);
                }
            }
            // 增加题目与章节知识点关系
            addQuestionChapterKnowles(bean, question);
            // 删除题目关联的额知识点
            questionKnowledgeService.deleteByQuestionId(question.getId());
            // 增加题目和知识点关联
            addQuestionKnowledge(bean.getKnowledgePoints(), question);
            // 添加索引到es
            updateQuestion2ES(question);

            if (!CollectionUtils.isEmpty(dto.getChilds())) {
                if (!CollectionUtils.isEmpty(dto.getChilds())) {
                    //直接删除子试题
                    QueryWrapper qw = new QueryWrapper();
                    qw.eq("parent_id", question.getId());
                    this.deleteByCondition(qw);
                    //todo 添加子试题
                    dto.setId(question.getId());
                    saveChildrenQuestion(dto, dto.getChilds());
                }
            }

            questionIds.add(bean.getId());
        }
        //解析状态：0->解析中；1->解析失败；2->解析成功；3->导入失败；4-> 导入成功
//        importLog.setQuestionIds(StringUtils.joinList(questionIds, ","));
//        importLog.setStatus(4);
//        questionImportLogService.update(importLog);
        return null;
    }

    private QuestionDto converQuestion(QuestionDTO questionDTO) {
        QuestionDto questionDto = new QuestionDto();
        questionDto.setTitle(questionDTO.getTitle());
        questionDto.setSubjectId(questionDTO.getSubjectId());
        questionDto.setQuestionNo(questionDTO.getIndex());
        if (questionDTO.getDifficult() != null) {
            //难度转换
            Integer jyDifficult = convert2JyDifficult(questionDTO.getDifficult());
            questionDto.setDifficult(jyDifficult);
        }
        if (!CollectionUtils.isEmpty(questionDTO.getOptionList())) {
            //转换选项
            JSON json = converRightAnswer(questionDTO.getOptionList());
            questionDto.setOption(json);
            List<QuestionOptionDto> optionDtos = JSONObject.parseArray(json.toJSONString(), QuestionOptionDto.class);
            questionDto.setOptions(optionDtos);
        }
        if (!CollectionUtils.isEmpty(questionDTO.getRightAnswerList())) {
            //转换正确答案
            JSON json = converRightAnswer(questionDTO.getRightAnswerList());
            questionDto.setRightAnswer(json);
        }
        if (questionDTO.getRightAnswerList() != null) {
            questionDto.setRightAnswer((JSON) JSON.toJSON(questionDTO.getRightAnswerList()));

        }
        //解析
        if (!StringUtils.isEmpty(questionDTO.getAnalysis())) {
            questionDto.setAnalysis(questionDTO.getAnalysis());
        }
        questionDto.setStartRow(questionDTO.getStartRow());
        questionDto.setEndRow(questionDTO.getEndRow());
        questionDto.setDataRight(questionDTO.getDataRight());
        //子试题
        if (!CollectionUtils.isEmpty(questionDTO.getChildren())) {
            List<QuestionDto> childrenList = new ArrayList<>();
            for (QuestionDTO dto : questionDTO.getChildren()) {
                QuestionDto children = converQuestion(dto);
                childrenList.add(children);
            }
            questionDto.setChilds(childrenList);
        }
        return questionDto;
    }

    //转换箐优网难度
    private Integer convert2JyDifficult(Integer difficult) {
        switch (difficult) {
            case 1:
                return 11;
            case 2:
                return 12;
            case 3:
                return 13;
            case 4:
                return 14;
            case 5:
                return 15;
        }
        return 11;
    }

    //正确答案转换
    private JSON converRightAnswer(List<QuestionOptionDTO> rightAnswer) {
        if (CollectionUtils.isEmpty(rightAnswer)) {
            return null;
        }
//        List<QuestionOptionDto> rightAnswerList = rightAnswer.stream().map(item -> {
//            QuestionOptionDto rightAnswerDto = new QuestionOptionDto();
//            rightAnswerDto.setName(item.getName());
//            rightAnswerDto.setContent(item.getContent());
//            rightAnswerDto.setOrderNo(item.getOrderNumber());
//            rightAnswerDto.setChilds(findChildren(item.getChildren(), new ArrayList<>()));
//            return rightAnswerDto;
//        }).collect(Collectors.toList());
//        return (JSON) JSON.toJSON(rightAnswerList);
        return (JSON) JSON.toJSON(rightAnswer);
    }

    private List<QuestionOptionDto> findChildren(List<QuestionOptionDTO> children, List<QuestionOptionDto> optionDtos) {
        if (CollectionUtils.isEmpty(children)) {
            return optionDtos;
        } else {
            for (QuestionOptionDTO child : children) {
                QuestionOptionDto rightAnswerDto = new QuestionOptionDto();
                rightAnswerDto.setName(child.getName());
                rightAnswerDto.setContent(child.getContent());
                rightAnswerDto.setNo(child.getNo());
                if (!CollectionUtils.isEmpty(child.getChilds())) {
                    findChildren(child.getChilds(), optionDtos);
                }
                optionDtos.add(rightAnswerDto);
            }
            return optionDtos;
        }
    }

    private void addQuestion2ES(Question question) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("id", question.getId());
        map.put("subjectId", question.getSubjectId());
        if(question.getBasicType()==7){
            map.put("title", HtmlUtils.delHTMLTag(question.getTitle() + question.getConnectingOptionStr()));
        }else {
            map.put("title", HtmlUtils.delHTMLTag(question.getTitle() + question.getOptionStr()));
        }
        elasticSearchService.addIndex(map, question.getId(), TikuEsContant.ES_INDEX_TIKU,
                TikuEsContant.TYPE.ES_INDEX_TYPE_QUESTION);
    }

    private void updateQuestion2ES(Question question) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("id", question.getId());
        map.put("subjectId", question.getSubjectId());
        if(question.getBasicType()==7)
        map.put("title", HtmlUtils.delHTMLTag(question.getTitle() + question.getOptionStr()));
        elasticSearchService.updateIndex(map, question.getId(), TikuEsContant.ES_INDEX_TIKU,
                TikuEsContant.TYPE.ES_INDEX_TYPE_QUESTION);
    }

    private Map<String, String> getKnowledge(List<Knowledge> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        String first = list.get(0).getId();
        String second = list.get(1) == null ? "" : list.get(1).getId();
        list.remove(0);
        list.remove(1);
        String three = "";
        if (!list.isEmpty()) {
            for (Knowledge k : list) {
                three += k.getId();
                three += ",";
            }
            three = three.substring(0, three.length() - 1);
        }
        Map<String, String> map = new HashMap<String, String>(3);
        map.put("first", first);
        map.put("second", second);
        map.put("three", three);
        return map;
    }

    @Override
    public List<QuestionTypeCountDto> getQuestionByType(QuestionQueryRequest bean) {
        List<QuestionTypeCountDto> groupByType = this.dao.getQuestionCountGroupByType(bean);
        if (CollectionUtils.isEmpty(groupByType)) {
            return new ArrayList<>();
        }
        List<QuestionTypeRelation> questionTypeRelations = questionTypeRelationService.queryBySubject(bean.getSubject());

        Map<String, String> jyTypeMap = questionTypeRelations.stream().collect(Collectors.toMap(item -> item.getJyQuestionType().toString(), item -> item.getJyQuestionTypeName(), (a, b) -> a));
        for (QuestionTypeCountDto questionTypeCountDto : groupByType) {
            String typeName = jyTypeMap.get(questionTypeCountDto.getType());
            questionTypeCountDto.setTypeName(typeName);
        }
        return groupByType;
    }

    @Override
    public List<QuestionDto> querySimilarQuestions(List<Map<String, String>> repeatInfos) {
        Set<String> ids = new HashSet<>(repeatInfos.size());
        for (Map<String, String> repeatInfo : repeatInfos) {
            ids.add(repeatInfo.get("questionId"));
        }
        // 按照相似度倒叙排序
        Collections.sort(repeatInfos, new Comparator<Map<String, String>>() {
            @Override
            public int compare(Map<String, String> map1, Map<String, String> map2) {
                return Double.valueOf(map2.get("similarDegree")).compareTo(Double.valueOf(map1.get("similarDegree")));
            }
        });
        List<QuestionDto> result = new ArrayList<>();
        for (Map<String, String> repeatInfo : repeatInfos) {
            String quetionId = repeatInfo.get("questionId");
            for (String id : ids) {
                if (id.equals(quetionId)) {
                    QuestionDto question = getQuestion(quetionId, null);
                    if (question != null) {
                        result.add(question);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public void batchModifyQuestionUseCount(List<String> questionIdList, Integer addOrReduce) {
        if (CollectionUtils.isEmpty(questionIdList)) {
            return;
        }
        QueryWrapper<Question> qw = new QueryWrapper<>();
        qw.in("id", questionIdList);
        List<Question> questions = this.dao.selectList(qw);
        if (CollectionUtils.isEmpty(questions)) {
            return;
        }
        questions.forEach(item -> {
            if (addOrReduce.equals(1)) {
                item.setUseCount(item.getUseCount() == null ? 1 : item.getUseCount() + 1);
            } else {
                item.setUseCount(item.getUseCount() == null ? 0 : item.getUseCount() - 1);
            }
        });
        this.batchUpdate(questions);
    }

    public void addQuestion_syncData(QuestionSaveRequest bean) {
        QuestionTypeRelation questionTypeRelation = questionTypeRelationService.queryByJyQuestionType(bean.getSubjectId(), bean.getType());
        if (StringUtils.isEmpty(bean.getTitle())) {
            return;
        }

        Question question = new Question();
        question.setId(bean.getId());
        question.init();
        question.setTitle(bean.getTitle());

        question.setType(bean.getType());
        if (questionTypeRelation != null) {
            question.setBasicType(questionTypeRelation.getToolQuestionType());
            question.setBasicTypeName(questionTypeRelation.getToolQuestionTypeName());
        }
        question.setSubjectId(bean.getSubjectId());
        question.setDifficult(bean.getDifficult() == null ? null : bean.getDifficult());
        question.setGradeRangeId(bean.getGradeRangeId());
        question.setGradeId(bean.getGradeId());
        question.setYearId(bean.getYear());
        question.setCategory(bean.getCategory());
        question.setLabels(bean.getLabels());
        question.setSource(bean.getSource());
        question.setSourceFrom(1);
        question.setStatus(3);

        if (bean.getOption() != null) {
            String option = bean.getOption().toJSONString();
            question.setOptionContent(option);
        }
        question.setRightAnswer(bean.getRightAnswer() == null ? null : bean.getRightAnswer().toJSONString());
        question.setQuestionMd5(question.genarateMd5());

        // 计算选项的排列方式
        QuestionUtils.calculateOptionArrangements(question);
        this.dao.insert(question);
        QuestionDetail questionDetail = new QuestionDetail();
        questionDetail.setId(question.getId());
        questionDetail.setAnalysis(bean.getAnalysis() == null ? "" : bean.getAnalysis());
        questionDetail.setExamPoint(bean.getExamPoint());
        questionDetail.setAnalysisPay(bean.getAnalysisPay());
        questionDetail.setAnalysisVideo(bean.getAnalysisVideo());
        questionDetailMapper.insert(questionDetail);

        //子试题
        if (!CollectionUtils.isEmpty(bean.getChilds())) {
            if (!CollectionUtils.isEmpty(bean.getChilds())) {
                //todo 添加子试题
                QuestionDto questionDto = new QuestionDto();
                questionDto.setId(question.getId());
                saveChildrenQuestion(questionDto, bean.getChilds());
            }
        }

        //试题来源
        if (!CollectionUtils.isEmpty(bean.getQuestionSources())) {
            for (int i = 0; i < bean.getQuestionSources().size(); i++) {
                QuestionSource questionSource = bean.getQuestionSources().get(i);
                questionSource.setQuestionId(question.getId());
                questionSource.setOrderNo((i + 1));
                questionSourceService.insert(questionSource);
            }
        }
        // 增加题目和知识点关联
        addQuestionKnowledge(bean.getKnowledgePoints(), question);
    }

    @Override
    public List<ExerciseStudentQuestionDto> queryQuestionDetail(List<String> id,String paperId) {
        return this.dao.queryQuestionDetail(id,paperId);
    }
}
